#include "lib/print.h"
#include "dev/timer.h"
#include "dev/uart.h"
#include "dev/plic.h"
#include "trap/trap.h"
#include "proc/cpu.h"
#include "memlayout.h"
#include "riscv.h"
#include "dev/virtio.h"  // 确保 virtio_disk_intr 的声明可用

// 中断信息
char* interrupt_info[16] = {
    "U-mode software interrupt",      // 0
    "S-mode software interrupt",      // 1
    "reserved-1",                     // 2
    "M-mode software interrupt",      // 3
    "U-mode timer interrupt",         // 4
    "S-mode timer interrupt",         // 5
    "reserved-2",                     // 6
    "M-mode timer interrupt",         // 7
    "U-mode external interrupt",      // 8
    "S-mode external interrupt",      // 9
    "reserved-3",                     // 10
    "M-mode external interrupt",      // 11
    "reserved-4",                     // 12
    "reserved-5",                     // 13
    "reserved-6",                     // 14
    "reserved-7",                     // 15
};

// 异常信息
char* exception_info[16] = {
    "Instruction address misaligned", // 0
    "Instruction access fault",       // 1
    "Illegal instruction",            // 2
    "Breakpoint",                     // 3
    "Load address misaligned",        // 4
    "Load access fault",              // 5
    "Store/AMO address misaligned",   // 6
    "Store/AMO access fault",         // 7
    "Environment call from U-mode",   // 8
    "Environment call from S-mode",   // 9
    "reserved-1",                     // 10
    "Environment call from M-mode",   // 11
    "Instruction page fault",         // 12
    "Load page fault",                // 13
    "reserved-2",                     // 14
    "Store/AMO page fault",           // 15
};

// in trap.S
// 内核中断处理流程
extern void kernel_vector();

// 初始化trap中全局共享的东西
void trap_kernel_init()
{
    plic_init();
    plic_inithart();
    timer_create();
    // printf("trap_kernel_init() is finished\n");
}

// 各个核心trap初始化
void trap_kernel_inithart()
{
    // 设置当前 hart 的陷入处理程序的入口地址为 kernel_vector
    w_stvec((uint64)kernel_vector);

    // 启用 S-mode 中断
    intr_on();

    // 将当前 CPU 的 noff 计数器设置为 0，表示强制开启中断支持
    mycpu()->noff = 0;
}

// 外设中断处理 (基于PLIC)
void external_interrupt_handler()
{
    // 获取中断号
    int irq = plic_claim();
    
    if (irq == 0){
        return ; // 忽略中断
    }
    else if (irq == UART_IRQ) {
        // 处理 UART 中断
        uart_intr();
    } else if (irq == VIRTIO_IRQ){
        // 处理virtio中断
        virtio_disk_intr();
    }
    else {
        // 输出未被定义的中断
        printf("Unexpected interrupt irq = %d\n", irq);
    }

    // 完成外部中断处理
    plic_complete(irq);
}

// 时钟中断处理 (基于CLINT)
void timer_interrupt_handler()
{
    w_sip(r_sip() & ~2);// 通过清除sip中的SSIP位确认软件中断

    if(mycpuid() == 0)
    {
        timer_update();//增加滴答数
        // printf("ticks = %d\n",timer_get_ticks());
    }

    // printf("cpu %d: dida\n",r_tp());

}

// 在kernel_vector()里面调用
// 内核态trap处理的核心逻辑
void trap_kernel_handler()
{
    // printf("enter trap_kernel_handler\n");
    // timer_interrupt_handler();
    uint64 sepc = r_sepc();          // 记录了发生异常时的pc值
    uint64 sstatus = r_sstatus();    // 与特权模式和中断相关的状态信息
    uint64 scause = r_scause();      // 引发trap的原因
    uint64 stval = r_stval();        // 发生trap时保存的附加信息(不同trap不一样)

    // 确认trap来自S-mode且此时trap处于关闭状态
    assert(sstatus & SSTATUS_SPP, "trap_kernel_handler: not from s-mode");
    assert(intr_get() == 0, "trap_kernel_handler: interreput enabled");

    int trap_id = scause & 0xFF;  // 获取完整的trap_id
    bool is_interrupt = (scause & (1ULL << 63)) != 0;

    // 中断异常处理核心逻辑
    if (is_interrupt) {
        switch (trap_id) {
            case 1: // S-mode software interrupt
                timer_interrupt_handler();
                break;
            case 5: // S-mode timer interrupt
                timer_interrupt_handler();
                break;
            case 9: // S-mode external interrupt
                external_interrupt_handler();
                break;
            default:
                if (trap_id < 16) {
                    printf("Interrupt: %s\n", interrupt_info[trap_id]);
                } else {
                    printf("Unexpected interrupt: trap_id=%d\n", trap_id);
                }
                printf("trap occurred at sepc=0x%x, stval=0x%x\n", (uint32)sepc, (uint32)stval);
                break;
        }
    } else {  // 异常
        if (trap_id < 16) {
            printf("Exception: %s\n", exception_info[trap_id]);
        } else {
            printf("Unexpected exception: trap_id=%d\n", trap_id);
        }
        printf("trap occurred at sepc=0x%x, stval=0x%x\n", (uint32)sepc, (uint32)stval);
    }

    w_sepc(sepc);
    w_sstatus(sstatus);
    // printf("finish trap_kernel_handler\n");
}